﻿using Microsoft.Extensions.DependencyInjection;
using Minio.DataModel;
using Modules.Manager;
using Modules.Person.Repositories;
using Modules.Project.Entitys;
using Modules.Project.Repositories;
using PmSoft;
using PmSoft.ApplicationContext;
using PmSoft.Exceptions;
using System.Collections.Generic;
using static Modules.Person.PersonConstants;

namespace Modules.Person
{
    /// <summary>
    /// 人员相关服务
    /// </summary>
    [UseDI(ServiceLifetime.Scoped)]
    public class PersonService
    {
        private readonly PersonInfoRepository personInfoRepository;
        private readonly ProjectGroupMemberRepository projectGroupMemberRepository;
        private readonly PersonBankService personBankService;
        private readonly PersonCertificateService personCertificateService;
        private readonly PersonCertificateSpecialityService personCertificateSpecialityService;
        private readonly PersonAttachmentService personAttachmentService;
        private readonly PersonIdCardIndexer personIdCardIndexer;
        private readonly IApplicationContext applicationContext;

        public PersonService(PersonInfoRepository personInfoRepository,
            ProjectGroupMemberRepository projectGroupMemberRepository,
            PersonBankService personBankService,
            PersonCertificateService personCertificateService,
            PersonCertificateSpecialityService personCertificateSpecialityService,
            PersonAttachmentService personAttachmentService,
            PersonIdCardIndexer personIdCardIndexer,
            IApplicationContext applicationContext)
        {
            this.personInfoRepository = personInfoRepository;
            this.projectGroupMemberRepository = projectGroupMemberRepository;
            this.personBankService = personBankService;
            this.applicationContext = applicationContext;
            this.personCertificateService = personCertificateService;
            this.personCertificateSpecialityService = personCertificateSpecialityService;
            this.personAttachmentService = personAttachmentService;
            this.personIdCardIndexer = personIdCardIndexer;
        }

        public void CreatePersonInfo(PersonInfo entity)
        {
            if (personInfoRepository.ExistsByPersonCardNumber(entity))
                throw new BusinessException($"身份证号：{entity.CardNumber}  已存在，不能创建");
            personInfoRepository.Insert(entity);
        }

        public void DeletPersons(IEnumerable<int> ids)
        {
            foreach (int id in ids)
                DeletPerson(id);
        }

        public void DeletPerson(int id)
        {
            personIdCardIndexer.Remove(id);//删除索引
            personInfoRepository.DeleteByEntityId(id);
        }

        public PersonInfo? GetPerson(int id)
        {
            return personInfoRepository.Get(id);
        }

        public IEnumerable<PersonInfo> GetPersons(IEnumerable<int> personIds)
        {
            return personInfoRepository.PopulateEntitiesByEntityIds(personIds);
        }

        public IPagedList<PersonInfo> GetPersons(PersonQuery query, int pageIndex, int pageSize)
        {
            return personInfoRepository.GetPersons(query, pageIndex, pageSize);
        }

        public void UpdatePersonInfo(PersonInfo data)
        {
            if (personInfoRepository.ExistsByPersonCardNumber(data, data.PersonId))
                throw new BusinessException($"身份证号：{data.CardNumber}  已存在，不能修改");
            personInfoRepository.Update(data);
        }

        /// <summary>
        /// 根据身份证号码获取人员信息
        /// </summary>
        /// <param name="cardNo"></param>
        /// <returns></returns>
        public PersonInfo? GetPersonByCardNo(string cardNo)
        {
            int? personId = personIdCardIndexer.GetId(cardNo);
            if (personId.HasValue && personId > 0)
                return GetPerson(personId.Value);
            return null;
        }

        public IEnumerable<PersonInfo> SearchPersonByCardNumber(string cardNumber, int managerId)
        {
            return personInfoRepository.SearchPersonByCardNumber(cardNumber, managerId);
        }

        /// <summary>
        /// 根据身份证号码获取人员信息
        /// </summary>
        /// <param name="cardNo"></param>
        /// <returns></returns>
        public List<PersonInfo> GetPersonsByCardNos(IEnumerable<string> cardNos)
        {
            List<PersonInfo> list = new();
            foreach (var cardNo in cardNos)
            {
                int? personId = personIdCardIndexer.GetId(cardNo);
                if (!personId.HasValue || personId <= 0) continue;
                var person = GetPerson(personId.Value);
                if (person == null) continue;
                list.Add(person);
            }
            return list;
        }

        public void CreatePersonUpdateMember(PersonInfo person, ProjectGroupMember member, string? cardNo, string? bankName, List<PersonCertificate> certificates, List<PersonAttachment> attachs, List<PersonCertificateSpeciality> specials)
        {
            if (projectGroupMemberRepository.ExistsByProjectPerson(member, member.Id))
            {
                throw new BusinessException($"当前项目下人员:{person.Name}已存在");
            }
            try
            {
                applicationContext.Transaction.Begin();//开始事务
                UpdatePersonInfo(person);
                var oldMembers = projectGroupMemberRepository.GetProjectGroupMembersByPersonId(person.PersonId);

                if (member.Id > 0)
                {
                    projectGroupMemberRepository.Update(member);
                }
                else
                {
                    #region 登记人员的情况下需要将该人员所有的班组信息改为离场

                    foreach (var item in oldMembers)
                    {
                        item.Status = 进出场状态.离场;
                        item.EndDate = DateTime.Now;
                        projectGroupMemberRepository.Update(item);
                    }

                    #endregion 登记人员的情况下需要将该人员所有的班组信息改为离场

                    if (member.IsLeader == true)
                    {
                        //查询当前班组下有没有班组长
                        ProjectGroupMember? leaderMember = projectGroupMemberRepository.GetProjectGroupMembersByProjectId(member.ProjectId).FirstOrDefault(a => a.CorpId == member.CorpId && a.GroupId == member.GroupId && a.IsLeader == true);
                        if (leaderMember != null)
                        {
                            leaderMember.IsLeader = false;
                            projectGroupMemberRepository.Update(leaderMember);
                        }
                    }
                    if (member.PostCategory.HasValue)
                    {
                        if (member.PostCategory.Value == 管理岗位类型.劳资管理员)
                        {
                            member.Status = 进出场状态.离场;
                        }
                        member.IsManager = true;
                    }
                    projectGroupMemberRepository.Insert(member);
                }

                #region 银行卡

                PersonBank? bank = personBankService.GetDefaultPersonBankByIdCard(person.CardNumber);

                if (bank == null && !string.IsNullOrEmpty(cardNo))
                {
                    bank = new()
                    {
                        IdCard = person.CardNumber,
                        Type = 工资卡类型.银行卡,
                        CardNo = cardNo,
                        BankName = bankName ?? "",
                        CreateTime = DateTime.Now,
                    };
                    personBankService.CreateOrUpdate(bank);
                }
                else if (bank != null && !string.IsNullOrEmpty(cardNo))
                {
                    bank.CardNo = cardNo;
                    bank.BankName = bankName ?? "";
                    personBankService.UpdatePersonBankNoTransaction(bank);
                }

                #endregion 银行卡

                #region 证书

                //删除证书
                personCertificateService.DeleteByPersonId(person.PersonId);
                //新增证书
                foreach (var item in certificates)
                {
                    item.CreateTime = DateTime.Now;
                    personCertificateService.Create(item);
                }
                //新增证书专业
                foreach (var item in specials)
                {
                    personCertificateSpecialityService.Create(item);
                }
                //新增证书附件
                foreach (var item in attachs)
                {
                    item.Id = Guid.NewGuid().ToString().Replace("-", "");
                    personAttachmentService.Create(item);
                }

                #endregion 证书

                applicationContext.Transaction.Complete();//完成事务
            }
            catch (Exception ex)
            {
                applicationContext.Transaction.Abort();//回滚事务
                throw new BusinessException($"写入用户数据失败,原因：{ex.Message}");
            }
        }

        public PersonInfo? GetPersonBySecurityId(int securityId)
        {
            return personInfoRepository.GetPersonBySecurityId(securityId);
        }

        public IEnumerable<PersonInfo> GetPersonsByNames(string keywords)
        {
            return personInfoRepository.GetPersonByNames(keywords);
        }

        public IEnumerable<PersonInfo> GetPersonsByPersonIds(IEnumerable<int> personIds)
        {
            return personInfoRepository.PopulateEntitiesByEntityIds(personIds);
        }

        public IEnumerable<PersonInfo> GetPersonsByCardNumbers(IEnumerable<string> cardNumbers)
        {
            return personInfoRepository.GetPersonsByCardNumbers(cardNumbers);
        }

        public IEnumerable<PersonInfo> GetPersonInfosByProjectId(int projectId)
        {
            return personInfoRepository.GetPersonInfosByProjectId(projectId);
        }

        public IPagedList<PersonInfo> GetPersonInfosByProjectIdAndCorpId(string? keywords, int? projectId, int? corpId, int pageIndex, int pageSize)
        {
            return personInfoRepository.GetPersonInfosByProjectIdAndCorpId(keywords, projectId, corpId, pageIndex, pageSize);
        }
    }
}